#include "watermarkwindow.h"
#include "global.h"
#include "macro.h"
#include "qrencode/qrencode.h"

#include <QDebug>
#include <QPainter>
#include <QCloseEvent>
#include <QTimerEvent>
#include <QDateTime>
#include <QApplication>

#ifdef Q_OS_WIN32
    #include <windows.h>
#endif

WatermarkWindow::WatermarkWindow(QWidget *parent)
    : QMainWindow(parent)
    , m_datetimeId(0)
    , m_topmostId(0)
    , m_pScreen(nullptr)
{
    setAttribute(Qt::WA_TransparentForMouseEvents);
    setWindowFlags(Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool);
    setAttribute(Qt::WA_TranslucentBackground);

    m_datetimeId = startTimer(60 * 1000);   // 每分钟刷新一次
//    m_topmostId = startTimer(1000);         // 每秒钟更新一次置顶

#ifdef Q_OS_WIN32
    // 服务下启动，需要先取消置顶一次
    ::SetWindowPos(HWND(winId()), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
    ::SetWindowPos(HWND(winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
#endif
}

WatermarkWindow::~WatermarkWindow()
{
    if (m_datetimeId != 0)
    {
        killTimer(m_datetimeId);
    }
    if (m_topmostId != 0)
    {
        killTimer(m_topmostId);
    }
}

void WatermarkWindow::setScreen(QScreen *screen)
{
    m_pScreen = screen;
}

void WatermarkWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    switch (Global::instance().waterType())
    {
        case WATER_TYPE_TEXT:
            drawTextWM();
            break;
        case WATER_TYPE_IMAGE:
            drawImageWM();
            break;
        case WATER_TYPE_QRCODE:
            drawQRCodeWM();
            break;
        case WATER_TYPE_DARK:
            drawDarkWM();
            break;
        case WATER_TYPE_MATRIX:
            drawMatrixWM();
            break;
        default:
            break;
    }
}

void WatermarkWindow::closeEvent(QCloseEvent *event)
{
    // 忽略人为的关闭操作
    event->setAccepted(event->spontaneous());
}

void WatermarkWindow::timerEvent(QTimerEvent *event)
{
    int timerId = event->timerId();
    if (timerId == m_topmostId)
    {
#ifdef Q_OS_WIN32
        ::SetWindowPos(HWND(winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
#endif
#ifdef Q_OS_LINUX
        raise();
#endif
    }
    else if (timerId == m_datetimeId)
    {
        update();
    }
}

void WatermarkWindow::drawTextWM()
{
    QString watermarkContent = GL.textContent();
    watermarkContent.replace("{日期}", QDate::currentDate().toString("yyyy-MM-dd"))
    .replace("{时间}", QTime::currentTime().toString("HH:mm"));
    if (watermarkContent.isEmpty())
    {
        return;
    }

    // 计算文字宽度（像素）
    QFontMetrics fontMetrics(GL.textFont());
    QRect fontRect = fontMetrics.boundingRect(QRect(0, 0, 10000, 10000), Qt::TextWordWrap, watermarkContent);
    int space = GL.textDensity();
    int rotate = GL.textSlope();
    int w = fontRect.width();
    fontRect.moveTop(-w);

    setWindowOpacity(1);

    QPainter painter(this);
    painter.setPen(GL.textColor());
    painter.setFont(GL.textFont());

    while (true)
    {
        QRect contentRect = fontRect;

        painter.translate(contentRect.center());
        painter.rotate(-rotate);
        contentRect.moveTo(-contentRect.width() / 2, -contentRect.height() / 2);
        painter.drawText(contentRect, Qt::AlignLeft | Qt::AlignTop, watermarkContent);
        painter.resetTransform();
        painter.translate(0, 0);

        fontRect.moveLeft(fontRect.x() + fontRect.width() + space);
        if (fontRect.x() > geometry().width())
        {
            fontRect.moveLeft(0);
            fontRect.moveTop(fontRect.y() + fontRect.height() + space);
        }
        if (fontRect.y() > geometry().height() + w)
        {
            break;
        }
    }
}

void WatermarkWindow::drawImageWM()
{
    int scale = GL.imageScale();
    int slope = GL.imageSlope();

    QPixmap pixmap = GL.imagePixmap();
    QSize size = pixmap.size();
    size *= scale / 100.0f;
    pixmap = pixmap.scaled(size);
    pixmap = pixmap.transformed(QTransform().rotate(slope));

    int x = 0;
    int y = 0;
    calculatePosition(GL.imagePos(), pixmap.width(), pixmap.height(), x, y);
    int opacity = GL.imageOpacity();

    setWindowOpacity(1);

    QPainter painter(this);
    painter.setOpacity(opacity / 255.0f);
    painter.drawPixmap(x, y, pixmap);
}

void WatermarkWindow::drawQRCodeWM()
{
    QString watermarkContent = GL.qrContent();
    watermarkContent.replace("{日期}", QDate::currentDate().toString("yyyy-MM-dd"))
    .replace("{时间}", QTime::currentTime().toString("HH:mm"));
    if (watermarkContent.isEmpty())
    {
        watermarkContent = " ";
    }

    // 生成二维码
    QRcode *qrcode = QRcode_encodeString(watermarkContent.toStdString().c_str(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
    int width = GL.qrSize();
    int height = GL.qrSize();
    int qrcode_width = qrcode->width > 0 ? qrcode->width : 1;
    double scale_x = (double)width / (double)qrcode_width;
    double scale_y = (double)height / (double)qrcode_width;

    int _x = 0;
    int _y = 0;
    calculatePosition(GL.qrPos(), width, height, _x, _y);

    setWindowOpacity(1);

    QPainter painter(this);
    painter.setPen(Qt::NoPen);
    painter.setBrush(GL.qrColor());

    for (int y = 0; y < qrcode_width; y++)
    {
        for (int x = 0; x < qrcode_width; x++)
        {
            unsigned char b = qrcode->data[y * qrcode_width + x];
            if (b & 0x01)
            {
                QRectF r(x * scale_x + _x, y * scale_y + _y, scale_x, scale_y);
                painter.drawRects(&r, 1);
            }
        }
    }
}

void WatermarkWindow::drawDarkWM()
{
    QString watermarkContent = GL.darkContent();
    watermarkContent.replace("{日期}", QDate::currentDate().toString("yyyy-MM-dd"))
    .replace("{时间}", QTime::currentTime().toString("HH:mm"));
    if (watermarkContent.isEmpty())
    {
        return;
    }

    // 计算文字宽度（像素）
    QFontMetrics fontMetrics(GL.darkFont());
    QRect fontRect = fontMetrics.boundingRect(QRect(0, 0, 10000, 10000), Qt::TextWordWrap, watermarkContent);
    int space = GL.darkDensity();
    int rotate = GL.darkSlope();
    int w = fontRect.width();
    fontRect.moveTop(-w);

    setWindowOpacity(GL.darkOpacity() / 255.0f);

    QPainter painter(this);
    painter.setBrush(QColor(0, 0, 0));
    painter.drawRect(rect());

    painter.setPen(GL.darkColor());
    painter.setFont(GL.darkFont());

    while (true)
    {
        QRect contentRect = fontRect;

        painter.translate(contentRect.center());
        painter.rotate(-rotate);
        contentRect.moveTo(-contentRect.width() / 2, -contentRect.height() / 2);
        painter.drawText(contentRect, Qt::AlignLeft | Qt::AlignTop, watermarkContent);
        painter.resetTransform();
        painter.translate(0, 0);

        fontRect.moveLeft(fontRect.x() + fontRect.width() + space);
        if (fontRect.x() > geometry().width())
        {
            fontRect.moveLeft(0);
            fontRect.moveTop(fontRect.y() + fontRect.height() + space);
        }
        if (fontRect.y() > geometry().height() + w)
        {
            break;
        }
    }
}

void WatermarkWindow::drawMatrixWM()
{
    setWindowOpacity(1);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(GL.matrixColor());

    QString content = GL.matrixContent();
    int diam = GL.matrixDiam();     // 点直径
    int space = GL.matrixInterval();
    int length = GL.matrixLength();        // 点阵边长，决定点间距
    int x = -length;
    int y = -length;
    while (true)
    {
        for (int i = 0; i < 9; i++)
        {
            int _x = x + (i % 3) * (length + space);
            int _y = y + (i / 3) * (length + space);

            uint32_t code = Global::instance().matrixCodeByString(content.at(i));
            for (int j = 0; j < 25; j++)
            {
                int __x = _x + (j % 5) * length / 5;
                int __y = _y + (j / 5) * length / 5;
                if ((code >> j & 1) == 1)
                {
                    painter.drawEllipse(__x, __y, diam, diam);
                }
            }
        }
        x += 3 * (length + space);
        if (x > geometry().width())
        {
            x = -length;
            y += 3 * (length + space);
        }
        if (y > geometry().height())
        {
            break;
        }
    }
}

void WatermarkWindow::calculatePosition(int position, int width, int height, int &x, int &y)
{
    QRect rect = m_pScreen ? m_pScreen->availableGeometry() : geometry();

    switch (position)
    {
        case 0:
            x = (rect.width() - width) / 2;
            y = (rect.height() - height) / 2;
            break;
        case 1:
            x = 0;
            y = 0;
            break;
        case 2:
            x = (rect.width() - width) / 2;
            y = 0;
            break;
        case 3:
            x = rect.width() - width;
            y = 0;
            break;
        case 4:
            x = 0;
            y = rect.height() - height;
            break;
        case 5:
            x = (rect.width() - width) / 2;
            y = rect.height() - height;
            break;
        case 6:
            x = rect.width() - width;
            y = rect.height() - height;
            break;
        default:
            break;
    }
}
